import base64
import pickle

from django.shortcuts import render
from django import http
# Create your views here.
from django.views import View
import json

from django_redis import get_redis_connection

from goods.models import SKU
from meiduo_mall.utlis.response_code import RET

#商品添加到购物车
class CartView(View):
    def post(self,request):

        # 1,获取参数
        dict_data = json.loads(request.body.decode())
        sku_id = dict_data.get("sku_id")
        count = dict_data.get("count")
        selected = dict_data.get("selected", True)

        # 2,校验参数
        # 2,1 为空校验
        if not all([sku_id, count]):
            return http.JsonResponse({"code": RET.PARAMERR, "errmsg": "参数不全"})

        # 2,2 将count转整数
        try:
            count = int(count)
        except Exception as e:
            return http.JsonResponse({"code": RET.PARAMERR, "errmsg": "count有误"})

        # 2,3 判断sku_id对象是否存在
        try:
            sku = SKU.objects.get(id=sku_id)
        except Exception as e:
            return http.JsonResponse({"code": RET.NODATA, "errmsg": "sku不存在"})

        # 2,4 判断库存是否足够
        if count > sku.stock:
            return http.JsonResponse({"code": RET.NODATA, "errmsg": "库存不足"})
        #3.数据入库
        user=request.user
        if user.is_authenticated:#已登陆的用户，保存到redis
            # 3,1,获取redis对象
            redis_conn = get_redis_connection("cart")

            # 3,2 添加数据到购物车
            redis_conn.hincrby("cart_%s" % user.id, sku_id, count)

            # 3,3 判断选中状态
            if selected:
                redis_conn.sadd("selected_%s" % user.id, sku_id)

            # 3,4 返回响应
            return http.JsonResponse({"code": RET.OK})
        else:#未登陆的用户保存到cookie
            #4,1获取cookie购物车数据,如果有旧的数据就去出来,如果没有也不会报错
            cookie_cart = request.COOKIES.get("cart")

            #4,2 转换成字典
            cookie_cart_dict = {}
            if cookie_cart:#如果能取到旧的cookie数据,就将字符解码成字典
                cookie_cart_dict = pickle.loads(base64.b64decode(cookie_cart.encode()))

            #4,3 添加数据到字典中,
            #如果新前端新传来的的商品id(sku_id),旧cookie已经存在,就获取旧的数量,然后加上新的数量
            if sku_id in cookie_cart_dict:
                old_count = cookie_cart_dict[sku_id]["count"]#旧数量
                count += old_count#新旧累加

            cookie_cart_dict[sku_id] = {#给商品赋值数量,勾选状态
                "count":count,
                "selected":selected
            }

            #4,4 将字典转成字符串,返回
            cookie_cart = base64.b64encode(pickle.dumps(cookie_cart_dict)).decode()
            response = http.JsonResponse({"code": RET.OK})
            response.set_cookie("cart",cookie_cart)#设置到cookie
            return response


    def get(self,request):#超链接标签都用get
        # 1,取出用户对象
        user = request.user

        # 2,判断用户登陆状态
        if user.is_authenticated:
            # 2,1 获取redis中的购物车数据
            redis_conn = get_redis_connection("cart")
            cart_dict = redis_conn.hgetall("cart_%s" % user.id)  # 哈希获取该用户所有的购物车数据,哈希是字典,vlues又是以将值对存在
            selected_list = redis_conn.smembers("selected_%s" % user.id)

            # 2,2 拼接数据
            sku_list = []
            for sku_id, count in cart_dict.items():
                sku = SKU.objects.get(id=sku_id)
                sku_dict = {
                    "id": sku.id,
                    "default_image_url": sku.default_image_url.url,
                    "name": sku.name,
                    "price": str(sku.price),
                    "count": int(count),
                    "selected": str(sku_id in selected_list),#如果在列表里边就是True,前端js识别不了大写所以要转字符串
                    "amount": str(sku.price * int(count))
                }
                sku_list.append(sku_dict)

            # 2,3 返回响应
            return render(request, 'cart.html', {"sku_list": sku_list})
        else:
            # 3,1 获取cookie数据
            cookie_cart=request.COOKIES.get("cart")
            #3.2数据转换
            cookie_cart_dict={}
            if cookie_cart:
                cookie_cart_dict=pickle.loads(base64.b64decode(cookie_cart.encode()))

            # 3,3 数据拼接
            sku_list=[]
            for sku_id,selected_count in cookie_cart_dict.items():
                sku=SKU.objects.get(id=sku_id)
                sku_dict={
                    "id":sku_id,
                    "default_image_url":sku.default_image_url.url,
                    "name":sku.name,
                    "price":str(sku.price),
                    "count":int(selected_count["count"]),
                    "amount":str(sku.price*int(selected_count["count"])),
                    "selected": str(selected_count["selected"]),

                }
                sku_list.append(sku_dict)

            #3.4返回响应
            return render(request,"cart.html",context={"sku_list":sku_list})

    def put(self,request):#登陆用户的价格合计，与勾选状态实现

        # 1,获取参数
        dict_data=json.loads(request.body.decode())
        sku_id=dict_data.get("sku_id")
        count=dict_data.get("count")
        selected=dict_data.get("selected",True)#获取seleced的bool值,如果获取不到就赋值True

        # 2,校验参数
        # 2,1 为空校验
        if not all([sku_id,count]):
            return http.JsonResponse({"code":RET.PARAMERR,"errmsg":"参数不全"},status=400)

         # 2,2 商品是否存在
        try:
            sku=SKU.objects.get(id=sku_id)
        except Exception:
            return  http.JsonResponse({"code":RET.NODATA,"errmsg":"商品不存在"},status=400)
        # 2,3 将count转成整数
        try:
            count=int(count)

        except Exception as e:
            return http.JsonResponse({"code": RET.NODATA,"errmsg": "参数有误"},status=400)

         # 2,4 数量是否充足
        if count>sku.stock:
            return http.JsonResponse({"code": RET.NODATA,"errmsg": "库存不足"},status=400)

        # 3,数据入库
        user=request.user
        if user.is_authenticated:
            #3.1获取redis对象
            redis_conn=get_redis_connection("cart")

            # 3,2 设置数据
            redis_conn.hset("cart_%s"%user.id,sku_id,count)

            if selected:#判断该商品是否勾选,勾选就添加商品id,即商品合计会增加该商品的价钱
                redis_conn.sadd("selected_%s" % user.id, sku_id)
            else:#不勾选就删除商品id，即不计算不勾选的商品
                redis_conn.srem("selected_%s" % user.id, sku_id)

            # 3,3 拼接数据
            sku_dict = {
                "id": sku.id,
                "default_image_url": sku.default_image_url.url,
                "name": sku.name,
                "price": str(sku.price),
                "count": int(count),
                # "selected": str(selected),
                "selected": selected,
                "amount": str(sku.price * int(count))
            }

            # 3,4,返回响应
            return http.JsonResponse({"code": RET.OK, "cart_sku": sku_dict})

        else:
            #4.1获取cookie数据
            cookie_cart=request.COOKIES.get("cart")
            #4.2数据转换
            cookie_cart_dict={}
            if cookie_cart:

                cookie_cart_dict=pickle.loads(base64.b64decode(cookie_cart.encode()))

            #4.3修改数据,前端返回给的修改内容

            cookie_cart_dict[sku_id]={
                "count":count,
                "selected":selected

            }
            #4.3.1 拼接数据，修改完后重新拼接
            sku_dict={
                "id":sku.id,
                "default_image_url":sku.default_image_url.url,
                "name":sku.name,
                "price":str(sku.price),
                "count":int(count),
                "selected":selected,
                "amount":str(sku.price*int(count))
            }
            #4.4重新设置cookie,返回响应
            response=http.JsonResponse({"code":RET.OK,"cart_sku":sku_dict})
            cookie_cart=base64.b64encode(pickle.dumps(cookie_cart_dict)).decode()
            response.set_cookie("cart",cookie_cart)


            return response


    def delete(self,request):
        #1.获取参数
        dict_data=json.loads(request.body.decode())
        sku_id=dict_data.get("sku_id")

        #2.校验参数
        #2.1为空校验
        if not sku_id:
            return http.JsonResponse({"code":RET.PARAMERR,"errmsg":"参数不全"},status=400)
        #2.2判断sku对象是否存在
        try:
            sku=SKU.objects.get(id=sku_id)
        except Exception as e:
            return http.JsonResponse({"code":RET.PARAMERR,"errmsg":"商品不存在"},status=400)
        #3.数据入库（删除）
        user=request.user
        if user.is_authenticated:#已经登陆的用户
            #3.1删除redis数据
            redis_coon=get_redis_connection("cart")
            redis_coon.hdel("cart_%s"%user.id,sku_id)
            redis_coon.srem("selected_%s"%user.id,sku_id)

            #3.2返回响应
            return http.JsonResponse({"code":RET.OK})

        else:#未登录用户，删除购物车数据
            #4.1获取cookie参数
            cookie_cart=request.COOKIES.get("cart")
            #4.2数据转换
            cookie_cart_dict={}
            if cookie_cart:
                cookie_cart_dict=pickle.loads(base64.b64decode(cookie_cart.encode()))
            #4.3删除数据
            if sku_id in cookie_cart_dict:
                del cookie_cart_dict[sku_id]

            #4.4设置cookie数据，返回响应
            response=http.JsonResponse({"code":RET.OK})
            cookie_cart=base64.b64encode(pickle.dumps(cookie_cart_dict)).decode()
            response.set_cookie("cart",cookie_cart)

            return response

#购物车全选视图函数
class CartsAllSelectView(View):
    def put(self,request):
        #1.获取参数
        dict_data=json.loads(request.body.decode())
        selected=dict_data.get("selected")

        #2.校验参数
        try:
            selected=bool(selected)
        except Exception as e:
            return http.JsonResponse(status=400)
        #3.数据入库
        user=request.user
        if user.is_authenticated:#已登陆
            #3.1获取redis
            redis_conn=get_redis_connection("cart")

            #3.2修改数据
            cart_dict=redis_conn.hgetall("cart_%s"%user.id)
            sku_ids=cart_dict.keys()

            if selected:
                redis_conn.sadd("selected_%s"%user.id,*sku_ids)#sku_ids是个列表,*sku_ids相当于*args,在这里就是拆包的意思.
            else:
                redis_conn.srem("selected_%s"%user.id,*sku_ids)

            #3.3返回响应
            return http.JsonResponse({"code":RET.OK})
        else:#未登录
            cookie_cart=request.COOKIES.get("cart")

            #4.2 数据转换
            cookie_cart_dict={}
            if cookie_cart:
                cookie_cart_dict=pickle.loads(base64.b64decode(cookie_cart.encode()))

                # 获取到的字典格式->cookie_cart_dict = {'sku.id':{selecte:True或False,'count':数量}}

                #4.3修改数据
                for sku_id,selected_count in cookie_cart_dict.items():
                    selected_count["selected"]=selected #将selected全部改成跟前端传来的一样
                #4.4 转换数据，返回响应
                response=http.JsonResponse({"code":RET.OK})
                cookie_cart=base64.b64encode(pickle.dumps(cookie_cart_dict)).decode()
                response.set_cookie("cart",cookie_cart)
                return response


#简易购物车 的登陆与未登录
class CartsSimpleView(View):
    def get(self,request):

        # 1,获取用户
        user=request.user
        # 2,判断用户登陆状态
        if user.is_authenticated:
            #2.1获取redis数据
            redis_conn=get_redis_connection("cart")
            cart_dict=redis_conn.hgetall("cart_%s"%user.id)

            #2.2拼接数据
            sku_list=[]
            for sku_id,count in cart_dict.items():
                sku=SKU.objects.get(id=sku_id)
                sku_dict={
                    "id": sku.id,
                    "default_image_url": sku.default_image_url.url,
                    "name": sku.name,
                    "count": int(count)
                }
                sku_list.append(sku_dict)
            #2.3 返回响应
            return http.JsonResponse({"cart_skus":sku_list})
        else:
            # 3,1 获取cookie数据
            cookie_cart=request.COOKIES.get("cart")


            # 3,2 数据转换
            cookie_cart_dict={}
            if cookie_cart:
                cookie_cart_dict=pickle.loads(base64.b64decode(cookie_cart.encode()))

            # 3,3 数据拼接
            sku_list=[]
            for sku_id,seleted_count in cookie_cart_dict.items():
                sku=SKU.objects.get(id=sku_id)
                sku_dict={
                    "id": sku.id,
                    "default_image_url": sku.default_image_url.url,
                    "name": sku.name,
                    "count": int(seleted_count["count"])
                }
                sku_list.append(sku_dict)
            # 3,4 返回响应
            return http.JsonResponse({"cart_skus": sku_list})#前端需要的是"cart_skus"，所以就将sku_list赋值进去

























